package net.helix.engine.library.items;

import java.util.ArrayList;

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.glu.Sphere;
import org.lwjgl.util.vector.Vector3f;

import net.helix.core.Bounds;
import net.helix.core.geometry.Geometry_Material;
import net.helix.core.geometry.Geometry_Model;
import net.helix.core.transform.Transform;
import net.helix.core.transform.TransformDimension;
import net.helix.core.transform.ViewTransform;
import net.helix.element.Element;
import net.helix.element.Element_Mesh;
import net.helix.element.Element_Model;
import net.helix.element.ViewNodeElement;
import net.helix.engine.Engine;
import net.helix.engine.library.Library;
import net.helix.engine.properties.Properties;
import net.helix.engine.properties.Properties_Model;
import net.helix.engine.viewPath.ViewNode;
import net.helix.engine.viewPath.ViewPath;
import net.helix.graphics.GraphicsEngine;
import net.helix.graphics.GraphicsHelper;
import net.helix.physics.Collidable3d;

/**
 * A Geometry object should act like a movieclip with a mesh for
 * it's layers, nothing can be added or removed, however you can
 * toggle the render order and properties (including visibility)
 * of each mesh. On the properties for each mesh, a material
 * is set which contains all of the material properties
 * like ambient, diffuse, specular, emit, and reflective properties.
 * The material properties should also have an option for the
 * different types of illumination (.mtl illumination levels are
 * translated to a more multi-dimensional system). Checkboxes should
 * be available for turning on specular highlighting and diffuse, as
 * well as shadow casting and reflectivity with an environment map.
 * There should be a button (on the Mesh, not the material) which
 * allows the object to be shaded smooth or flat as well.
 * @author Runouw
 *
 */
public class LibraryItem_Model extends LibraryItem {
	
	private ArrayList<Element_Mesh> meshes;
	private Bounds bounds = new Bounds();
	
	public LibraryItem_Model(Library library, String name) {
		super(library, name);
		this.type = LibraryItemType.MODEL;
		
		meshes = null;
	}
	
	/**
	 * Gives this library item it's list of meshes. Make sure each Geometry.mesh
	 * already has a Geometry.Model applied. When you duplicate a mesh, it needs
	 * to create a new Geometry.Model as well (and new LibraryItems for them too)
	 * @param meshes
	 */
	public void setMeshes(ArrayList<Element_Mesh> meshes){
		this.meshes = meshes;
	}
	static Sphere sphere = new Sphere();
	@Override
	public void render(Properties properties) {
		
		bounds.clear();
		{
			int l = meshes.size();
			for(int i=0;i<l;i++){
				bounds.consider(meshes.get(i).getBounds());
			}
		}
		
		float w = bounds.getWidth();
		float h = bounds.getHeight();
		float d = bounds.getDepth();
		float r = (float) (Math.max(Math.max(w,  h), d)*Math.sqrt(2)/2);
		
		
		
		if(GraphicsHelper.isSphereInFrustrum(bounds.getMiddleX(), bounds.getMiddleY(), bounds.getMiddleZ(), r)){
			int l = meshes.size();
			for(int i=0;i<l;i++){
				meshes.get(i).render();
			}
			
			for(int i=0;i<l;i++){
				//meshes.get(i).renderCube();
			}
			
			
		}else{
		}
		
		
		
		
		//renderBoudingBox();
		
		
		
	}
	public void renderBoudingBox(){
		GL11.glPushMatrix();
		
		GL11.glTranslatef(bounds.getMiddleX(), bounds.getMiddleY(), bounds.getMiddleZ());
		
		GL11.glScalef(bounds.getWidth()/2, bounds.getHeight()/2, bounds.getDepth()/2);
		
		GL11.glLineWidth(1f);
		GL11.glColor4f(.5f, .5f, .5f, 1f);
		GraphicsHelper.drawDube();
		
		GL11.glPopMatrix();
		
	}
	
	@Override
	public void renderLibrary(Engine engine, int width, int height) {		
		ViewPath path = new ViewPath();
		
		Element_Model model = (Element_Model) createElement();
		
		path.setRoot(new ViewNode((ViewNodeElement) model, 0));
		
		ViewTransform viewTransform = new ViewTransform();
		
		Transform transform = new Transform(TransformDimension.THREE);
		
		
		
		bounds.clear();
		{
			int l = meshes.size();
			for(int i=0;i<l;i++){
				bounds.consider(meshes.get(i).getBounds());
			}
		}
		
		
		float distance = Math.max(Math.max(bounds.getWidth(), bounds.getHeight()), bounds.getDepth());
		
		distance = distance*.75f;
		
		transform.setTranslate(-bounds.getMeanX(), -bounds.getMeanY(), -bounds.getMeanZ() - distance);
		
		viewTransform.setTransform(transform);
		
		GraphicsEngine.switchRoot3D(engine, viewTransform, path, width, height, true);
		
		path.render();
		
	}

	@Override
	public Properties makeDefaultProperties() {
		return new Properties_Model();
	}

	@Override
	public Element createElement() {
		return new Element_Model(this);
	}

}
